import io
import copy
from utils.node import *
from utils.matrix_utils import *

log_buffer = io.StringIO()
logging.basicConfig(stream=log_buffer, level=logging.ERROR)


class Parser():
    arg_list_all = []

    def __init__(self, expr, config_dir=None, llm_mode=False, key_words=None):

        self.ori_expr = expr
        self.codes = r''
        self.root = None
        self.prefix_codes = {}
        self.unknown_vars = {}

        # 获取数据字典信息
        self.data = Data(config_dir)

        # 从json获取用户设置关键词
        if key_words != {} and key_words != None:
            key_words_dict = {key.upper(): value for key, value in key_words.items()}
            update_keywords(key_words_dict)

        # if llm_mode is set, errors will be ignored when parsing node
        self.data.llm_mode = llm_mode

    def set_root(self, node):

        self.root = node

    def pre_process(self, expr):

        _, expr = delete_bracket(expr)
        # 一些latex符号或运算符号替换为统一的符号
        expr = symbol_replace(expr, '∙', '*')
        expr = symbol_replace(expr, r'\mul', '*')
        expr = symbol_replace(expr, r'\cdot', '*')
        expr = symbol_replace(expr, r'\div', '/')
        expr = symbol_replace(expr, r'\left(', '(')
        expr = symbol_replace(expr, r'\right)', ')')
        expr = symbol_replace(expr, r'\leq', '<=')
        expr = symbol_replace(expr, r'\le', '<=')
        expr = symbol_replace(expr, r'\geq', '>=')
        expr = symbol_replace(expr, r'\ge', '>=')
        expr = symbol_replace(expr, r'：', ':')
        expr = expr.replace('≤', '<=')
        expr = expr.replace('≥', '>=')
        expr = expr.replace('·', '*')

        # 关键词替换
        expr = key_word_replace(expr, if_words, "IF")
        expr = key_word_replace(expr, elif_words, "ELSEIF")
        expr = key_word_replace(expr, else_words, "ELSE")
        expr = key_word_replace(expr, endif_words, "ENDIF")
        expr = key_word_replace(expr, for_words, "FOR")
        expr = key_word_replace(expr, endfor_words, "ENDFOR")
        expr = key_word_replace(expr, while_words, "WHILE")
        expr = key_word_replace(expr, endwhile_words, "ENDWHILE")

        # 一些临时变量名是非法/无效的
        d = copy.deepcopy(self.data.tmp_dict)
        for var in self.data.tmp_dict.keys():
            if 'name' not in self.data.tmp_dict[var].keys():
                if check_var_validity(var):
                    continue
                new_var = self.data.get_tmp_var()
                d[new_var] = d.pop(var)
                expr = expr.replace(var, new_var)
        self.data.tmp_dict = copy.deepcopy(d)
        c = copy.deepcopy(self.data.const_dict)
        pseudo_vars = {}
        for var in self.data.var_dict:
            pseudo_vars[var] = self.data.var_dict[var]['name']
        for var in self.data.const_dict:
            pseudo_vars[var] = self.data.const_dict[var]['name']
            c[pseudo_vars[var]] = c.pop(var)
        for var in self.data.tmp_dict:
            if 'name' in self.data.tmp_dict[var].keys():
                new_var = self.data.tmp_dict[var]['name']
                pseudo_vars[var] = new_var
                d[new_var] = d.pop(var)
        self.data.tmp_dict = d
        self.data.const_dict = c
        vars = []
        for var in pseudo_vars.keys():
            vars.append(var)
        # sort: length from long to short
        vars.sort(key=lambda s: len(s), reverse=True)
        for k in range(len(vars)):
            var = vars[k]
            i = 0
            # make sure the uniqueness of replacement
            while (pos := expr.find(var, i)) != -1:
                if if_independent_variable(expr, pos, len(var)):
                    # case: A[i][j] -> s[i].b[j]
                    c_var_pattern = r'[a-zA-Z_][a-zA-Z0-9_]*'
                    struct_array_pattern = '^' + c_var_pattern + r'\[\]\.' + c_var_pattern + r'\[\]'
                    if re.match(struct_array_pattern, pseudo_vars[var]):
                        l, l1, r, r1 = -1, -1, -1, -1
                        idx1, idx2 = '', ''
                        if expr[pos + len(var)] == '[':
                            l = pos + len(var)
                            r = bracket_match(expr, l)
                            idx1 = expr[l + 1:r]
                            if expr[r + 1] == '[':
                                l1 = r + 1
                                r1 = bracket_match(expr, l1)
                                idx2 = expr[l1 + 1:r1]
                                t = pseudo_vars[var].split('[]')[0] + f'[{idx1}]' + \
                                    pseudo_vars[var].split('[]')[1] + f'[{idx2}]'
                                if t not in self.data.global_vars.keys():
                                    ty = ''
                                    var_dicts = {**self.data.global_vars, **self.data.tmp_dict, **self.data.const_dict}
                                    ty = var_dicts[pseudo_vars[var]]['type']
                                    self.data.global_vars[t] = {'dim': '1*1', 'type': ty}
                                expr = expr[:pos] + t + expr[r1 + 1:]
                                continue
                    expr = expr[:pos] + expr[pos:].replace(var, '@$' + str(k) + '$', 1)
                    i = pos + 3
                else:
                    i = pos + len(var)
        while (pos1 := expr.find('@$')) != -1:
            pos2 = expr.find('$', pos1 + 2)
            idx = int(expr[pos1 + 2:pos2])
            expr = expr[:pos1] + expr[pos1:].replace('@$' + str(idx) + '$', pseudo_vars[vars[idx]], 1)
        return expr

    def parse_latex_symbol(self, fa, expr, op, pos):

        # parse the expression given latex symbol op
        # return the ending position of the scope of op and the corresponding code and the descendants
        end_pos = -1
        if op == r'\frac':
            l1, r1, l2, r2 = find_scope_op(expr, pos)
            node = Node(expr[pos:r2 + 1], fa=fa)
            node.set_op('frac')
            node.add_child(Node(expr[l1:r1]))
            node.add_child(Node(expr[l2:r2]))
            for child in node.children:
                self.parse_stmt(child)
            c1, c2 = node.children[0], node.children[1]
            if c1.op == 'matrix' and c2.op != 'matrix':
                c2.code = f'1/{c2.code}'
                self.insert_func(op='multiScalar', pos_node=node, is_matrix=True)
                return r2, node
            numerator = node.children[0].code
            if node.children[0].op not in ['var', 'num', 'func']:
                numerator = '({})'.format(numerator)
            denominator = node.children[1].code
            if node.children[1].op not in ['var', 'num', 'func']:
                denominator = '({})'.format(denominator)
            if fa.father.op == '=':
                node.code = '{} / {}'.format(numerator, denominator)
            else:
                node.code = '({} / {})'.format(numerator, denominator)
            end_pos = r2
        elif op == r'\sqrt':
            l1, r1 = find_scope_op(expr, pos)
            if 'sqrt' in self.data.func_dict.keys():
                expr = expr[:pos] + expr[pos + 1:l1 - 1] + '(' + expr[l1:r1] + ')' + expr[r1 + 1:]
                _, node = self.parse_function(fa, expr, 'Sqrtx', pos)
                fa.add_child(node)
                end_pos = r1
            else:
                node = Node(expr[pos:r1 + 1], fa=fa)
                node.set_op('sqrt')
                node.add_child(Node(expr[l1:r1]))
                for child in node.children:
                    self.parse_stmt(child)
                node.code = f'sqrt({node.children[0].code})'
                end_pos = r1
        elif op in latex2func_dict.keys():
            l1, r1 = find_scope_op(expr, pos)
            expr = expr[:pos] + expr[pos + 1:l1 - 1] + '(' + expr[l1:r1] + ')' + expr[r1 + 1:]
            _, node = self.parse_function(fa, expr, latex2func_dict[op], pos)
            fa.add_child(node)
            end_pos = r1
        elif op == r'\eqmulti':
            # piecewise function we defined
            l1, r1 = find_scope_op(expr, pos)
            var = expr[:pos].strip()
            lines = expr[l1:r1].split(',')
            s = r''
            for i, line in enumerate(lines):
                stmt, cond = line.split('@')
                # cond = make_condition(cond)
                if i == 0:
                    s += ('IF1(' + cond + '){' + var + '=' + stmt + ';}\n')
                else:
                    s += ('ELSEIF1(' + cond + '){' + var + '=' + stmt + ';}\n')
            s += 'ENDIF1'
            node = Node(s, op='branch', fa=fa)
            self._parse(node)
            end_pos = r1
        else:
            expr = expr[1:]
            node = Node(expr, fa=fa)
        return end_pos, node

    def parse_function(self, fa, expr, op, pos):

        l, r = find_scope_func(expr, pos)
        node = Node(expr[pos:r + 1])
        fa.add_child(node)
        node.set_op('func')
        args = find_function_args(expr[l: r])
        for i in range(len(args)):
            node.add_child(Node(args[i]))
            self.parse_stmt(node.children[-1])
            args[i] = node.children[-1].code
        arg_list = ', '.join(args)
        return_type = 'double'
        # 函数名在数据字典中
        if op in self.data.func_dict.keys():
            return_type = self.data.func_dict[op]['return_type']
            output_type = self.data.func_dict[op]['output_type']

            l1, r1 = find_scope_func(self.data.func_dict[op]['raw_func'], 0)
            param1 = str(self.data.func_dict[op]['raw_func'][l1:r1]).split(',')
            j = 0
            while j < len(param1):
                li = param1[j].split(' ')
                if li[0] == "float64":
                    args[j] = recong_float(args[j], False)
                j = j + 1
            for t in range(len(args)):
                arg_list = ', '.join(args)

            op = self.data.func_dict[op]['func_name']
            arg_num = self.data.func_dict[op]['raw_func'].count(',') + 1

            if ((output_type == "void") or (arg_num == len(args) and return_type == 'void')) and (
                    fa.father != None and 'body' != fa.father.op):
                erro_print(traceback.extract_stack(),
                           f"function {op} doesn't have return value, cannot be used as argument in function calling!")
        else:
            erro_print(traceback.extract_stack(), f"No function named {op}!")
            if self.data.llm_mode:
                node.fail_to_generate()
                return
        code = op + '(' + arg_list + ')'
        # 存储计算结果，函数复用
        '''
        # reuse calculation results
        if code in self.prefix_codes.keys():
            code = self.prefix_codes[code]['var_name']
        else:
            var = self.self.data.get_tmp_var()
            self.prefix_codes[code] = {
                'var_name': var, 'return_type': return_type}
            code = var
        '''
        node.code = code
        return r, node

    def parse_matrix(self, elements, node):
        # elements: type: [[str]]

        var_dicts = {**self.data.global_vars, **self.data.tmp_dict, **self.data.const_dict}
        dims = [len(elements), len(elements[0])]
        mat = ''
        code_lines = ''
        if node.father.op == '=' and node == node.father.children[-1]:
            mat = drop_square_brackets(node.father.children[0].code)
            if mat not in var_dicts.keys():
                new_var = self.data.get_recommend_name(mat)
                self.data.tmp_dict[new_var] = {'type': 'float64', 'dim': f'{dims[0]}*{dims[1]}'}
                if new_var != mat:
                    self.data.tmp_dict[mat] = {'name': new_var, 'type': 'float64', 'dim': f'{dims[0]}*{dims[1]}'}
                mat = new_var
            else:
                var_dim = [var_dicts[mat]['dim'].split('*')[0], var_dicts[mat]['dim'].split('*')[1]]
                # n*1->1*n
                if var_dim[1] == 1:
                    var_dim = [var_dim[1], var_dim[0]]
                if str(dims[0]) != var_dim[0] or str(dims[1]) != var_dim[1]:
                    erro_print(traceback.extract_stack(), f"Matrix dims not match!")
                    if self.data.llm_mode:
                        node.fail_to_generate()
                        return
            for i in range(dims[0]):
                for j in range(dims[1]):
                    code_lines += '    ' * node.level
                    if dims[0] == 1:
                        code_lines += f'{mat}[{j}] = {elements[i][j]};'
                    elif dims[1] == 1:
                        code_lines += f'{mat}[{i}] = {elements[i][j]};'
                    else:
                        code_lines += f'{mat}[{i}][{j}] = {elements[i][j]};'
                    code_lines += '\n'
            node.set_op('body')
            node.expr = code_lines.strip()
            self._parse(node)
            node.set_op('hook')
            node.father.set_op('body')
            return
        else:
            mat = self.data.get_tmp_var()
            self.data.tmp_dict[mat] = {'type': 'float64', 'dim': f'{str(dims[0])}*{str(dims[1])}'}
            fa = node.father
            son = node
            while fa.op != 'body':
                son = fa
                fa = fa.father
            for i in range(len(fa.children)):
                if fa.children[i] == son:
                    new_node = Node(op='body')
                    fa.add_child(new_node, i)
                    for j in range(dims[0]):
                        for k in range(dims[1]):
                            code_lines += '    ' * new_node.level
                            if dims[0] == 1:
                                code_lines += f'{mat}[{k}] = {elements[j][k]};'
                            elif dims[1] == 1:
                                code_lines += f'{mat}[{j}] = {elements[j][k]};'
                            else:
                                code_lines += f'{mat}[{j}][{k}] = {elements[j][k]};'
                            code_lines += '\n'
                    new_node.expr = code_lines.strip()
                    self._parse(new_node)
                    node.set_op('matrix')
                    node.set_code(mat)
                    return

    def insert_func(self, op, pos_node, l2r=False, is_matrix=False, flag=False):

        # pos_node->Node: node in which the function appears(e.g. node.expr = 'func(b)*c')
        # func_node->Node: func node which has already been parsed
        if is_matrix:
            if op == "transpose":
                process_matrix_transpose(self.data, pos_node)
            elif op == "inversion":
                process_matrix_inversion(self.data, pos_node)
            elif op == 'multiply':
                process_matrix_multiply(self.data, pos_node, l2r)
            elif op == 'multiScalar':
                process_matrix_multiScalar(self.data, pos_node, l2r)
            elif op == 'add' or op == 'sub':
                process_matrix_add_and_sub(op, self.data, pos_node, flag)
            elif op == 'equal':
                process_matrix_equal(self.data, pos_node)
            elif op == 'vector_cross':
                process_vector_cross(self.data, pos_node, l2r)

    def parse(self):

        # clear log buffer
        log_buffer.truncate(0)
        expr = self.pre_process(self.ori_expr)
        self.set_root(Node(expr, 'body'))
        self.root.set_lines((1, 1 + self.root.expr.count('\n')))
        self._parse(self.root)

    @parser_decorator
    def _parse(self, node: Node):

        if log_buffer.getvalue() != '':
            return
        expr = node.expr
        if node.op == 'body':
            s = expr
            while s != '':
                flag = False
                for word in key_words:
                    if s.find(word) == 0:
                        if s[len(word)] in '0123456789':
                            key_word = word + s[len(word)]
                        else:
                            if (word in note_words) or (
                                    word not in note_words and if_independent_variable(s, 0, len(word))):
                                key_word = ''
                            else:
                                continue
                        if word in if_words:
                            end_key_word = "ENDIF"
                            if key_word:
                                end_key_word += key_word[-1]
                            end_pos = s.find(end_key_word)
                            if end_pos == -1:
                                erro_print(traceback.extract_stack(), "No 'ENDIF' found!")
                                if self.data.llm_mode:
                                    node.fail_to_generate()
                                    return
                            node.add_child(Node(s[:end_pos], 'branch'))
                            s = s[end_pos + len(end_key_word):].strip()
                            flag = True
                        elif word in while_words:
                            end_key_word = "ENDWHILE"
                            if key_word:
                                end_key_word += key_word[-1]
                            end_pos = s.find(end_key_word)
                            if end_pos == -1:
                                erro_print(traceback.extract_stack(), "No 'ENDWHILE' found!")
                                if self.data.llm_mode:
                                    node.fail_to_generate()
                                    return
                            node.add_child(Node(s[:end_pos], 'loop_while'))
                            s = s[end_pos + len(end_key_word):].strip()
                            flag = True
                        elif word in for_words:
                            end_key_word = "ENDFOR"
                            if key_word:
                                end_key_word += key_word[-1]
                            end_pos = s.find(end_key_word)
                            if end_pos == -1:
                                erro_print(traceback.extract_stack(), "No 'ENDFOR' found!")
                                if self.data.llm_mode:
                                    node.fail_to_generate()
                                    return
                            node.add_child(Node(s[:end_pos], 'loop'))
                            s = s[end_pos + len(end_key_word):].strip()
                            flag = True
                        elif word in note_words:
                            if word == '//':
                                end_pos = s.find('\n')
                                if end_pos == -1:
                                    node.add_child(Node(s, 'note'))
                                    s = ''
                                    flag = True
                                else:
                                    node.add_child(Node(s[:end_pos], 'note'))
                                    s = s[end_pos:].strip()
                                    flag = True
                            elif word == '/*':
                                end_key_word = "*/"
                                end_pos = s.find(end_key_word)
                                if end_pos == -1:
                                    erro_print(traceback.extract_stack(), "No '*/' found!")
                                    if self.data.llm_mode:
                                        node.fail_to_generate()
                                        return
                                node.add_child(Node(s[:end_pos + 2], 'note'))
                                s = s[end_pos + len(end_key_word):].strip()
                                flag = True
                    if flag:
                        break
                if not flag and s != '':
                    end_pos = find_independent_symbol(s, ';')
                    if end_pos == -1:
                        erro_info = "No ';' found! Expression is:\n{}".format(s)
                        if node.lines != None:
                            s_pos = node.expr.find(s)
                            start_line = node.lines[0] + node.expr[:s_pos].count('\n')
                            end_line = start_line + s.count('\n')
                            erro_info = f"Wrong! From line {start_line} to line {end_line}\n" + erro_info
                        erro_print(traceback.extract_stack(), erro_info)
                        if self.data.llm_mode:
                            node.fail_to_generate()
                            return
                    node.add_child(Node(s[:end_pos]))
                    s = s[end_pos + 1:].strip()
            for child in node.children:
                self._parse(child)
        elif node.op == 'if':
            l = expr.find('(')
            r = bracket_match(expr, l)
            cond = expr[l + 1:r]
            _, body = delete_bracket(expr[r + 1:], '{')
            node.add_child(Node(cond, 'condition'))
            node.add_child(Node(body, 'body'))
            for child in node.children:
                self._parse(child)
        elif node.op == 'elseif':
            l = expr.find('(')
            r = bracket_match(expr, l)
            cond = expr[l + 1:r]
            _, body = delete_bracket(expr[r + 1:], '{')
            node.add_child(Node(cond, 'condition'))
            node.add_child(Node(body, 'body'))
            for child in node.children:
                self._parse(child)
        elif node.op == 'else':
            _, body = delete_bracket(expr, '{')
            if body == '':
                body = "NULL_STATEMENT();"
            node.add_child(Node(body, 'body'))
            for child in node.children:
                self._parse(child)
        elif node.op == 'condition':
            i = 0
            while i < len(expr):
                if expr[i] == '=' and i > 0 and i < len(expr) \
                        and expr[i + 1] != '=' and expr[i - 1] not in ['=', '>', '<', '!']:
                    expr = expr[:i + 1] + '=' + expr[i + 1:]
                    i += 2
                else:
                    i += 1
            node.add_child(Node(expr))
            for child in node.children:
                self._parse(child)
        elif node.op == 'branch':
            if_word, level = '', ''
            for word in if_words:
                if expr.find(word) == 0:
                    if_word = word
                    if expr[len(word)] in '0123456789':
                        level = expr[len(word)]
                    break
            elif_word = "ELSEIF"
            else_word = "ELSE"
            l = expr.find('(')
            r = bracket_match(expr, l)
            if expr[r + 1:].strip().find('{') != 0:
                # no { }
                start_pos = r
                r_if1 = expr[r + 1:].find(elif_word + level) + r + 1
                if r_if1 == r:
                    r_if1 = len(expr)
                r_if2 = expr[r + 1:].find(else_word + level) + r + 1
                if r_if2 == r:
                    r_if2 = len(expr)
                r_if = min(r_if1, r_if2)
            else:
                start_pos = expr[r + 1:].find('{') + r + 1
                r_if = bracket_match(expr, start_pos) + 1
            node.add_child(Node(expr[l:r_if], 'if'))  # if语句，必有
            s = expr[r_if:].strip()
            has_elif = False
            while (pos := s.find(elif_word + level)) != -1:
                has_elif = True
                l = s.find('(')
                r = bracket_match(s, l)
                if s[r + 1:].strip().find('{') != 0:
                    # no { }
                    start_pos = r
                    r_if1 = s[r + 1:].find(elif_word + level) + r + 1
                    if r_if1 == r:
                        r_if1 = len(s)
                    r_if2 = s[r + 1:].find(else_word + level) + r + 1
                    if r_if2 == r:
                        r_if2 = len(s)
                    r_elseif = min(r_if1, r_if2)
                else:
                    start_pos = s.find('{', r)
                    r_elseif = bracket_match(s, start_pos) + 1
                node.add_child(Node(s[l:r_elseif], 'elseif'))  # elseif语句
                s = s[r_elseif:].strip()
            if (pos := s.find(else_word + level)) != -1:
                if s[pos + len(else_word + level):].strip().find('{') != 0:
                    # no { }
                    start_pos = pos + len(else_word + level)
                    r_else = len(s)
                else:
                    start_pos = s.find('{')
                    r_else = bracket_match(s, start_pos) + 1
                    if s[r_else:].strip() != '':
                        r_else = len(s)
                node.add_child(Node(s[start_pos:r_else], 'else'))
            else:
                # 根据502语法规范，需要补充空的else语句
                if has_elif:
                    node.add_child(Node("NULL_STATEMENT();", 'else'))
            for child in node.children:
                self._parse(child)
        elif node.op == 'loop':
            l = expr.find('(')
            r = bracket_match(expr, l)
            cond = expr[l + 1:r]
            _, body = delete_bracket(expr[r + 1:], '{')
            node.add_child(Node(cond, 'loop_condition'))
            node.add_child(Node(body, 'body'))
            for child in node.children:
                self._parse(child)
        elif node.op == 'loop_while':
            l = expr.find('(')
            r = bracket_match(expr, l)
            cond = expr[l + 1:r]
            _, body = delete_bracket(expr[r + 1:], '{')
            s_init, s_cond, s_increment = loop_condition_transform(cond)
            if s_init != None:
                cond = s_cond
            node.add_child(Node(cond, 'condition'))
            node.add_child(Node(body, 'body'))
            for child in node.children:
                self._parse(child)
        elif node.op == 'loop_condition':
            s_init, s_cond, s_increment = loop_condition_transform(expr)
            node.add_child(Node(s_init))
            node.add_child(Node(s_cond))
            node.add_child(Node(s_increment))
            for child in node.children:
                self.parse_stmt(child)
        else:
            self.parse_stmt(node)
        node.generate_code()

    @parser_decorator
    def parse_stmt(self, node: Node):

        if log_buffer.getvalue() != '':
            return
        if node.expr in special_symbols:
            return
        # note operator, // /**/
        note_res = expr_note(node.expr)
        if note_res == 1:
            node.set_code(node.expr)
            return
        elif note_res == 2:
            node.set_code(node.expr)
            return
        # coposite operator, e.g. +=
        res = expr_composite_op(node.expr)
        if res != None:
            node.modify_expr(res)
            self.parse_stmt(node)
            return
        # if expr contains 'and', 'or'
        pos1, pos2, symb = expr_and_or(node.expr)
        if (pos1 != -1):
            node.set_op(symb)
            node.add_child(Node(node.expr[:pos1]))
            node.add_child(Node(node.expr[pos2:]))
            for child in node.children:
                self.parse_stmt(child)
                child.generate_code()
            node.code = '{} {} {}'.format(
                node.children[0].code, symb, node.children[1].code)
            return
        # 表达式是等式
        pos1, pos2, symb = expr_eq_neq(node.expr)
        if (pos1 != -1):
            # 特殊情况：处理连等
            if (eq_idxs := is_multi_eq(node.expr)) != [] and len(eq_idxs) > 1:
                vals = [val.strip() for val in node.expr.split('=')]
                fa = node.father
                son = node
                while fa.op != 'body':
                    son = fa
                    fa = fa.father
                for i in range(len(fa.children)):
                    if fa.children[i] == son:
                        for j in range(len(vals) - 1):
                            new_node = Node(f'{vals[j]} = {vals[-1]}')
                            fa.add_child(new_node, i + j)
                            self.parse_stmt(new_node)
                            new_node.generate_code()
                node.set_op('none')
                return
                # 特殊的赋值形式，形如：a[][i] = {0}等
            if (new_expr := assignment_node_process(self.data, node, pos1)) != '':
                node.expr = new_expr
                node.set_op('body')
                self._parse(node)
                return
            node.set_op(symb)
            node.add_child(Node(node.expr[:pos1]))
            node.add_child(Node(node.expr[pos2:]))
            symb_dict = ['<', '<=', '>', '>=']
            for child in node.children:
                self.parse_stmt(child)
                # 左值是矩阵展开式/向量展开式
                if child.op == 'matrix_left_value' or child.op == 'vec_left_value':
                    node.set_code(child.code)
                    node.set_op('body')
                    return
            if node.op == 'none':
                # 解析的过程中child已经把该节点解析完了
                return
            if node.children[-1].op not in ['hook', 'body']:
                c1, c2 = node.children[0], node.children[1]
                if c1.op == 'matrix' and c2.op == 'matrix' and symb == '=':
                    self.insert_func(op='equal', pos_node=node, is_matrix=True)
                    return
                elif c2.op == 'matrix' and symb == '=':
                    var_dicts = {**self.data.global_vars, **self.data.tmp_dict, **self.data.const_dict}
                    if c1.op == 'var' and c1.code not in var_dicts:
                        var_name = self.data.get_recommend_name(c1.code)
                        c1.set_op('matrix')
                        output_dim, output_type = get_matrix_dim_and_type(self.data, c2.code)
                        self.data.tmp_dict[var_name] = {'type': output_type, 'dim': output_dim}
                        if c1.code != var_name:
                            self.data.tmp_dict[c1.code] = {'name': var_name, 'type': output_type, 'dim': output_dim}
                        c1.code = var_name
                        self.insert_func(op='equal', pos_node=node, is_matrix=True)
                        return
                # elif c1.op == "matrix":
                #     # 报错
                #     erro_print(traceback.extract_stack(), "Matrix assignment error")
                elif symb in symb_dict:  # 条件判断语句中的不等式，主要处理连续不等情况，如if (a<b<c)
                    if node.children[-2].op in symb_dict and node.children[-1].op in symb_dict:
                        t1, t2 = node.children[-2], node.children[-1]
                        while len(t1.children) > 0 and t1.op != 'func':
                            t1 = t1.children[-1]
                        while len(t2.children) > 0 and t2.op != 'func':
                            t2 = t2.children[0]
                        node.code = '{} && ({} {} {}) && {}'.format( \
                            node.children[-2].code, t1.code, symb, t2.code, node.children[-1].code)
                        return
                    elif node.children[-2].op in symb_dict:
                        t = node.children[-2]
                        while len(t.children) > 0 and t.op != 'func':
                            t = t.children[-1]
                        node.code = '{} && ({} {} {})'.format(node.children[-2].code, t.code, symb,
                                                              node.children[-1].code)
                    elif node.children[-1].op in symb_dict:
                        t = node.children[-1]
                        while t.op in symb_dict:
                            t = t.children[0]
                        node.code = '({} {} {}) && {}'.format(node.children[-2].code, symb, t.code,
                                                              node.children[-1].code)
                    else:
                        node.code = '({} {} {})'.format(node.children[0].code, symb, node.children[1].code)
                else:
                    if symb == '=' and c1.op not in 'bit':
                        var_dicts = {**self.data.global_vars, **self.data.tmp_dict, **self.data.const_dict}
                        # 对于数组，获得其数组名
                        res = drop_square_brackets(c1.code)
                        # c1对应变量未知，尝试推断其维度（有可能是错的）
                        if c1.code not in var_dicts.keys():
                            if c1.code.find('.') == -1 and res not in var_dicts.keys():
                                var_name = self.data.get_recommend_name(c1.code)
                                output_dim, output_type = get_var_dim_and_type(self.data, c2)
                                self.data.tmp_dict[var_name] = {'type': output_type, 'dim': output_dim}
                                if c1.code != var_name:
                                    self.data.tmp_dict[c1.code] = {'name': var_name, 'type': output_type,
                                                                   'dim': output_dim}
                                c1.code = var_name
                                var_dicts[c1.code] = {'type': output_type, 'dim': output_dim}
                            if c1.code in var_dicts.keys() and var_dicts[c1.code]['type'].find('float') != -1:
                                if (c2.code.isdigit()):  # int 转 float
                                    c2.code = str(float(c2.code))
                    elif c1.op == 'bit':
                        print()
                    if c1.code in self.data.var_dict.keys():
                        if self.data.var_dict[c1.code]['type'] == "float64":
                            c2.code = recong_float(c2.code, False)
                    elif c1.code in self.data.tmp_dict.keys():
                        if self.data.tmp_dict[c1.code]['type'] == "float64":
                            c2.code = recong_float(c2.code, False)
                    elif c1.code in self.data.const_dict.keys():
                        if self.data.const_dict[c1.code]['type'] == "float64":
                            c2.code = recong_float(c2.code, False)
                    node.code = recong_float('{} {} {}'.format(c1.code, symb, c2.code), True)
                    if symb != '=':
                        node.code = '(' + node.code + ')'
            else:
                node.code = recong_float(node.children[-1].code, True)
            return
        # if expr contains '|', '&', '<<', '>>'
        pos1, pos2, symb = expr_bit_op(node.expr)
        if (pos1 != -1):
            node.set_op(symb)
            node.add_child(Node(node.expr[:pos1]))
            node.add_child(Node(node.expr[pos2:]))
            for child in node.children:
                self.parse_stmt(child)
                child.generate_code()
            node.code = '{} {} {}'.format(
                node.children[0].code, symb, node.children[1].code)
            return
        # find math symbols(e.g. +)
        pos1, pos2, symb = expr_add_sub(node.expr)
        if (pos1 != -1):
            if pos1 == 0:
                i = pos1 + 1
                while i < len(node.expr) and node.expr[i] in ' 0123456789 .':
                    i += 1
                if i > pos1 + 1:
                    if i == len(node.expr):
                        node.code = node.expr
                        node.set_op('num')
                        return
                    node.expr = '(' + node.expr[:i] + ')' + node.expr[i:]
                    self.parse_stmt(node)
                    return
            node.add_child(Node(node.expr[:pos1]))
            node.add_child(Node(node.expr[pos2:]))
            self.parse_stmt(node.children[0])
            child = node.children[0]
            # 从左到右逐个处理A-B-C的情况
            if child.op == 'matrix' and symb == '-':
                op = 'sub'
                next_pos = find_next_expression(node.expr, pos1)
                while next_pos != -1:
                    node.delete_child(node.children[-1])
                    node.add_child(Node(node.expr[pos1 + 1:next_pos]))
                    self.parse_stmt(node.children[-1])
                    self.insert_func(op=op, pos_node=node, is_matrix=True, flag=True)
                    child = Node(op='matrix', fa=node, code=node.code)
                    node.set_op('')
                    node.set_code('')
                    node.delete_child(node.children[0])
                    node.add_child(child, 0)
                    pos1 = next_pos
                    if node.expr[next_pos] == '-':
                        op = 'sub'
                        symb = '-'
                    else:
                        op = 'add'
                        symb = '+'
                    next_pos = find_next_expression(node.expr, pos1)
                    if next_pos == -1:
                        node.delete_child(node.children[-1])
                        node.add_child(Node(node.expr[pos1 + 1:]))
            elif child.op == 'None' and symb == '-':
                if is_num(node.expr):
                    node.set_op('num')
                    node.set_code(node.expr)
                    return
                node.expr = f'(-1)*{node.expr[pos2:]}'
                node.clear_children()
                self.parse_stmt(node)
                return
            for child in node.children:
                if child.op == None:
                    self.parse_stmt(child)
            op = 'add'
            if node.expr[pos1] == '+':
                node.set_op('add')
            else:
                node.set_op('sub')
                op = 'sub'
            c1, c2 = node.children[0], node.children[1]
            if c1.op == 'matrix' and c2.op == 'matrix':
                self.insert_func(op=op, pos_node=node, is_matrix=True)
                return
            else:
                node.code = '{} {} {}'.format(node.children[0].code, symb, node.children[1].code)
            if node.has_bra:
                if node.op not in ['var', 'matrix']:
                    node.code = '({})'.format(node.code)
            return
        pos1, pos2, symb = expr_mul_div(node.expr)
        if (pos1 != -1):
            node.add_child(Node(node.expr[:pos1]))
            self.parse_stmt(node.children[0])
            left_var_op = node.children[0].op
            left_var = node.children[0].code
            next_pos = find_next_expression(node.expr, pos1, 'mul')
            # 从左到右解析
            while next_pos != -1:
                child = Node(node.expr[pos1 + 1:next_pos], fa=node)
                self.parse_stmt(child)
                if node.expr[pos1] == '*':
                    if left_var_op == 'matrix' and child.op == 'matrix':
                        node.add_child(child)
                        self.insert_func(op='multiply', pos_node=node, l2r=True, is_matrix=True)
                        left_var = node.code
                        node.delete_child(node.children[-1])
                        node.children[0].set_code(node.code)
                        node.children[0].set_op('matrix')
                    elif left_var_op == 'matrix' or child.op == 'matrix':
                        node.add_child(child)
                        self.insert_func(op='multiScalar', pos_node=node, l2r=True, is_matrix=True)
                        left_var = node.code
                        left_var_op = 'matrix'
                        node.delete_child(node.children[-1])
                        node.children[0].set_code(node.code)
                        node.children[0].set_op('matrix')
                    else:
                        left_var_op = 'var'
                        left_var = '{} {} {}'.format(left_var, '*', child.code)
                        node.children[0].set_code(left_var)
                elif node.expr[pos1] == '×':
                    if left_var_op == 'matrix' and child.op == 'matrix':
                        node.add_child(child)
                        self.insert_func(op='vector_cross', pos_node=node, l2r=True, is_matrix=True)
                        left_var = node.code
                        node.delete_child(node.children[-1])
                        node.children[0].set_code(node.code)
                        node.children[0].set_op('matrix')
                    else:
                        erro_print(traceback.extract_stack(), "vector cross needs 2 matrice")
                        if self.data.llm_mode:
                            node.fail_to_generate()
                            return
                else:
                    # 除法，右边一定不能是matrix
                    if child.op == "matrix":
                        erro_print(traceback.extract_stack(), "matrix can not be divided")
                        if self.data.llm_mode:
                            node.fail_to_generate()
                            return
                    elif left_var_op == "matrix":
                        node.add_child(child)
                        child.code = f'1/{child.code}'
                        res = self.insert_func(op='multiScalar', pos_node=node, l2r=True, is_matrix=True)
                        left_var = node.code
                        left_var_op = 'matrix'
                        node.delete_child(node.children[-1])
                        node.children[0].set_code(node.code)
                        node.children[0].set_op('matrix')
                    else:
                        left_var_op = 'var'
                        left_var = '{} {} {}'.format(left_var, '/', child.code)
                        node.children[0].set_code(left_var)
                pos1 = next_pos
                next_pos = find_next_expression(node.expr, pos1, 'mul')
            node.add_child(Node(node.expr[pos1 + 1:]))
            for child in node.children:
                if child.op == None:
                    self.parse_stmt(child)
            if node.expr[pos1] == '*':
                node.set_op('mul')
                c1, c2 = node.children[0], node.children[1]
                if c1.op == 'matrix' and c2.op == 'matrix':
                    self.insert_func(op='multiply', pos_node=node, is_matrix=True)
                elif c1.op == 'matrix' or c2.op == 'matrix':
                    self.insert_func(op='multiScalar', pos_node=node, is_matrix=True)
                else:
                    node.code = '{} {} {}'.format(node.children[0].code, node.expr[pos1], node.children[1].code)
            elif node.expr[pos1] == '×':
                node.set_op('cross')
                c1, c2 = node.children[0], node.children[1]
                if c1.op == 'matrix' and c2.op == 'matrix':
                    self.insert_func(op='vector_cross', pos_node=node, is_matrix=True)
                else:
                    node.code = '{} * {}'.format(node.children[0].code, node.children[1].code)
                    # erro_print(traceback.extract_stack(), f'Not vectors for vector cross! {c1.code}, {c2.code}')
            else:
                node.set_op('div')
                c1, c2 = node.children[0], node.children[1]
                if c1.op == 'matrix' and c2.op != 'matrix':
                    c2.code = f'1/{c2.code}'
                    self.insert_func(op='multiScalar', pos_node=node, is_matrix=True)
                else:
                    node.code = '{} {} {}'.format(node.children[0].code, node.expr[pos1], node.children[1].code)
            if node.has_bra:
                if node.op not in ['var', 'matrix']:
                    node.code = '({})'.format(node.code)
            return
        if (pos := expr_pow(node.expr)) != -1:
            l1, r1, l2, r2 = find_scope_pow(node.expr, pos)
            node.add_child(Node(node.expr[l1:r1].strip()))
            node.add_child(Node(node.expr[l2:r2].strip()))
            node.set_op('pow')
            for child in node.children:
                self.parse_stmt(child)
            if node.children[-1].code.strip() == '2':
                node.code = '{} * {}'.format(
                    node.children[0].code, node.children[0].code)
            elif node.children[-1].code.strip() == 'T' and node.children[0].op == 'matrix':
                self.insert_func(op="transpose", pos_node=node, is_matrix=True)
            elif node.children[-1].expr.strip() == '-1' and node.children[0].op == 'matrix':
                self.insert_func(op="inversion", pos_node=node, is_matrix=True)
            elif node.children[-1].expr.strip() in ['*', '×'] and node.children[0].op == 'matrix':
                vec = node.children[0].code.strip()
                code_lines = ""
                mat = ""
                if node.father.op == '=':
                    mat = node.father.children[0].code
                    var_dicts = {**self.data.global_vars, **self.data.tmp_dict, **self.data.const_dict}
                    if mat not in var_dicts:
                        var_name = self.data.get_recommend_name(mat)
                        output_dim, output_type = get_matrix_dim_and_type(self.data, node.children[0].code)
                        self.data.tmp_dict[var_name] = {'type': output_type, 'dim': output_dim}
                        if mat != var_name:
                            self.data.tmp_dict[mat] = {'name': var_name, 'type': output_type, 'dim': output_dim}
                        node.father.children[0].code = var_name
                        mat = var_name
                    code_lines = generate_skew_symmetric_matrix_code(mat, vec)
                    node.expr = code_lines
                    node.set_op('body')
                    node.clear_children()
                    self._parse(node)
                    node.father.set_op('body')
                    node.set_op('hook')
                    return
                else:
                    mat = self.data.get_tmp_var()
                    self.data.tmp_dict[mat] = {'type': 'float64', 'dim': '3*3'}
                    code_lines = generate_skew_symmetric_matrix_code(mat, vec)
                    fa = node.father
                    son = node
                    while fa.op != 'body':
                        son = fa
                        fa = fa.father
                    for i in range(len(fa.children)):
                        if fa.children[i] == son:
                            new_node = Node(op='body')
                            new_node.expr = code_lines
                            self._parse(new_node)
                            node.set_code(mat)
                            node.set_op('matrix')
                            return
            else:
                # To be supported: Science Notation
                node.code = 'pow({}, {})'.format(
                    node.children[0].code, node.children[1].code)
            if node.has_bra:
                if node.op not in ['var', 'matrix']:
                    node.code = '({})'.format(node.code)
            return
        if node.expr == '':
            # sometimes '-' or '+' is a unary operator, and one of the children is None
            node.set_op('None')
            node.code = ''
            return
        if node.expr[0] == '(':
            tar_pos = bracket_match(node.expr, 0)
            node.modify_expr(node.expr[:tar_pos + 1] + '*' + node.expr[tar_pos + 1:])
            self.parse_stmt(node)
            return
        op, s_idx = detect_op(node.expr)
        if op == None:
            return
        if op == node.expr.strip():
            if op in self.data.global_vars.keys() or op in self.data.tmp_dict.keys() or op in self.data.const_dict.keys():
                # 在数据字典里，直接返回
                dim = [1]
                if op in self.data.global_vars.keys():
                    _, dim = get_var_type(op, self.data.global_vars)
                elif op in self.data.tmp_dict.keys():
                    _, dim = get_var_type(op, self.data.tmp_dict)
                    if 'name' in self.data.tmp_dict[op].keys():
                        op = self.data.tmp_dict[op]['name']
                elif op in self.data.const_dict.keys():
                    _, dim = get_var_type(op, self.data.const_dict)
                if dim != [1]:
                    node.set_op('matrix')
                else:
                    node.set_op('var')
                node.set_code(op)
                return
            if is_num(op) or is_scientific_notation(op):
                # 是数字
                node.set_op('num')
                node.code = op
            elif is_hex_num(op):
                node.set_op('num')
                node.code = standard_hex_num(op)
            elif is_unit_matrix(op):
                dim = get_unit_matrix_dim(op)
                if dim == None:
                    erro_print(traceback.extract_stack(), f"单位阵维度无法识别")
                    if self.data.llm_mode:
                        node.fail_to_generate()
                        return
                fa = node.father
                son = node
                while fa.op != 'body':
                    son = fa
                    fa = fa.father
                for i in range(len(fa.children)):
                    if fa.children[i] == son:
                        I_code = ''
                        I = self.data.get_tmp_var()
                        loop_var1 = self.data.get_tmp_var()
                        loop_var2 = self.data.get_tmp_var()
                        self.data.tmp_dict[I] = {'type': 'siint32', 'dim': f'{dim}*{dim}'}
                        self.data.tmp_dict[loop_var1] = {'type': 'siint32', 'dim': '1*1'}
                        self.data.tmp_dict[loop_var2] = {'type': 'siint32', 'dim': '1*1'}
                        I_code += f'FOR1 ({loop_var1}={0}:{dim - 1})\nFOR2 ({loop_var2}={0}:{dim - 1})\n'
                        I_code += f'IF1({loop_var1} == {loop_var2})\n'
                        I_code += f'{I}[{loop_var1}][{loop_var1}] = 1;\n'
                        I_code += f'ELSE1\n'
                        I_code += f'{I}[{loop_var1}][{loop_var2}] = 0;\nENDIF1'
                        I_code += 'ENDFOR2\nENDFOR1'
                        I_node = Node(I_code, 'body')
                        self._parse(I_node)
                        fa.add_child(I_node, i)
                        node.set_code(I)
                        node.set_op('matrix')
                return
            else:
                # vector/matrix, 被方括号括起来的形式。如[a, b, c]
                if op[0] == '[' and bracket_match(op, 0) == len(op) - 1:
                    # node是赋值语句左值的情况
                    # e.g. [tmp1, tmp2] = VecA;
                    from_latex = False
                    if node.father.op == '=' and node == node.father.children[0]:
                        if is_latex_matrix(op):
                            # 1) 是latex格式矩阵/向量
                            elements = parse_latex_matrix(op[1:-1])
                            code_lines = node.father.expr
                            tmp_var = self.data.get_tmp_var()
                            code_lines = code_lines.replace(node.expr, tmp_var) + ';'
                            dims = [len(elements), len(elements[0])]
                            for i in range(dims[0]):
                                for j in range(dims[1]):
                                    if dims[0] == 1:
                                        code_lines += f'\n{elements[0][j]} = {tmp_var}[{j}];'
                                    elif dims[1] == 1:
                                        code_lines += f'\n{elements[i][0]} = {tmp_var}[{i}];'
                                    else:
                                        code_lines += f'\n{elements[i][j]} = {tmp_var}[{i}][{j}];'
                            new_node = Node(expr=code_lines, op='body')
                            node.add_child(new_node)
                            self._parse(new_node)
                            node.set_code(new_node.code)
                            node.set_op('matrix_left_value')
                            return
                        else:
                            # 2) 是形如[tmp1, tmp2]的向量。注，里面必须是标量
                            elements = [var.strip() for var in op[1:-1].split(',')]
                            right_value_vec = node.father.expr.split('=')[-1].strip()
                            var_dicts = {**self.data.global_vars, **self.data.tmp_dict, **self.data.const_dict}
                            if right_value_vec not in var_dicts.keys():
                                erro_print(traceback.extract_stack(), f"找不到向量 {right_value_vec}！")
                                if self.data.llm_mode:
                                    node.fail_to_generate()
                                    return
                            elif (int)(var_dicts[right_value_vec]['dim'].split('*')[-1]) != len(elements):
                                erro_print(traceback.extract_stack(), f"向量赋值维度不匹配 {node.father.expr}！")
                                if self.data.llm_mode:
                                    node.fail_to_generate()
                                    return
                            code_lines = ""
                            for i in range(len(elements)):
                                code_lines += f"{elements[i]} = {right_value_vec}[{i}];\n"
                            new_node = Node(expr=code_lines, op='body')
                            node.add_child(new_node)
                            self._parse(new_node)
                            node.set_code(new_node.code)
                            node.set_op('vec_left_value')
                            return
                    # 处理Latex格式矩阵，形如\begin{matrix}\end{matrix}的格式
                    if is_latex_matrix(op):
                        elements = parse_latex_matrix(op[1:-1])
                        self.parse_matrix(elements, node)
                        return
                    if op.find(';') != -1:
                        vars = op[1:-1].split(';')
                        if ',' in vars[0].strip() or ' ' in vars[0].strip():
                            elements = []
                            if ',' in vars[0].strip():
                                for line in vars:
                                    line = [var.strip() for var in line.split(',')]
                                    elements.append(line)
                            elif ' ' in vars[0].strip():
                                for line in vars:
                                    line = line.strip()
                                    line = [var.strip() for var in line.split(' ')]
                                    elements.append(line)
                            self.parse_matrix(elements, node)
                            return
                    elif op.find(',') != -1:
                        vars = independent_split(op[1:-1], ',')
                    elif op.find(r'\n') != -1:
                        vars = independent_split(op[1:-1], '\n')
                    else:
                        # warning 有隐患
                        vars = op[1:-1].split()
                    for i in range(len(vars)):
                        node.add_child(Node(vars[i]))
                        self.parse_stmt(node.children[-1])
                        vars[i] = node.children[-1].code
                    process_vector_matrix(self.data, node, vars)
                    return
                # 数组元素， e.g. a[10]
                if process_array(self.data, node, op):
                    return
                # op is a var
                if check_var_validity(op):
                    node.set_op('var')
                    node.code = op
                    if op not in self.data.tmp_dict.keys() and op not in self.data.global_vars.keys() \
                            and op not in self.data.const_dict.keys() and op not in self.unknown_vars.keys():
                        self.unknown_vars[op] = node

                elif op in self.data.const_dict.keys():
                    node.set_op('const')
                    node.code = self.data.const_dict[op]['name']
                elif (var := self.data.is_struct(op)) != None:
                    # 可能是结构体等
                    node.set_op('var')
                    var_dicts = {**self.data.global_vars, **self.data.tmp_dict, **self.data.const_dict}
                    if 'name' in var_dicts[var].keys():
                        new_var = var_dicts[var]['name']
                        node.code = new_var + op.replace(var, new_var, 1)
                        self.data.global_vars[new_node] = {"type": var_dicts[var]["type"], "dim": "1*1"}
                        node.set_code(new_node)
                    else:
                        node.code = op
                else:
                    i = 0
                    while op[i] in '0123456789.':
                        i += 1
                    # 单精度浮点数，例：1.2f
                    if i < len(op) and op[i] == 'f':
                        i += 1
                    num = op[:i]
                    if is_num(num):
                        node.set_op('mul')
                        node.add_child(Node(num))
                        node.add_child(Node(op[i:]))
                        self.parse_stmt(node.children[0])
                        self.parse_stmt(node.children[1])
                        node.code = '{} * {}'.format(node.children[0].code, node.children[1].code)
                    else:
                        # print ('Warning! invalid var name', op)
                        if op[0] == '|' and op[-1] == '|':
                            node.add_child(Node(op[1:-1]))
                            self.parse_stmt(node.children[0])
                            if node.children[0].op != 'matrix':
                                node.set_op('abs')
                                node.code = 'Fabsx({})'.format(node.children[0].code)
                            else:
                                process_vector_norm_matrix_det(self.data, node)
                        else:
                            # unary op, e.g. ++, --
                            pos, var, symb = expr_unary_op(node.expr)
                            if symb:
                                node.add_child(Node(var))
                                self.parse_stmt(node.children[0])
                                node.set_op(symb)
                                if pos == 0:
                                    node.code = f'{symb}{node.children[0].code}'
                                else:
                                    node.code = f'{node.children[0].code}{symb}'
                            else:
                                node.set_op('var')
                                node.code = op
                        # raise Exception('invalid var name!', op)
        else:
            if op[0] == '\\':
                # 处理latex符号
                pos, new_node = self.parse_latex_symbol(node, node.expr, op, s_idx)
            else:
                # 处理位运算（位运算书写格式参照伪代码语法规范）
                var_dicts = {**self.data.global_vars, **self.data.tmp_dict, **self.data.const_dict}
                if op in var_dicts.keys() and var_dicts[op]['type'] in \
                        ['siint32', 'unint32', 'siint08', 'unint08', 'siint16', 'unint16', 'llong64', 'ulong64']:
                    s = node.expr[len(op):].strip()
                    if s[0] == '(' and bracket_match(s, 0) == len(s) - 1:
                        bit = s[1:-1]
                        code = get_bit_from_var(op, bit)
                        node.code = code
                        node.op = 'bit'
                        return
                # 处理函数
                pos, new_node = self.parse_function(node, node.expr, op, s_idx)
            # 隐式乘号（如a=b sinx(x))以及其他后处理
            self.post_process(op, s_idx, pos, node, new_node)

    def post_process(self, op, s_idx, pos, node, new_node):

        # node->Node: original node which is parsing
        # new_node: already parsed node(latex symbol or function), whose expr is part of node's expr

        # if new_node's type is func, a independent sentence to process the function is needed
        if log_buffer.getvalue() != '':
            return
        if new_node.op == 'func':
            if op in self.data.func_dict.keys():
                func_node_process(op, self.data, node, new_node)
            else:
                # 如果latex符号存在对应的库函数
                if op in latex2func_dict.keys():
                    op = latex2func_dict[op]
                    func_node_process(op, self.data, node, new_node)
                else:
                    erro_print(traceback.extract_stack(), 'No func \'{}\' in the Data Dictionary!'.format(op))
                    if self.data.llm_mode:
                        node.fail_to_generate()
                        return
        # 隐式乘号
        if op == r'\eqmulti':
            node.copy_node(new_node)
            return
        if s_idx > 0 and pos < len(node.expr) - 1:
            node.set_op('mul')
            node.add_child(Node(node.expr[:s_idx]))
            node.add_child(Node(node.expr[s_idx:]))
            self.parse_stmt(node.children[0])
            node.children[-1].set_op('mul')
            node.children[-1].add_child(new_node)
            node.children[-1].add_child(Node(node.expr[pos + 1:]))
            self.parse_stmt(node.children[-1].children[-1])
            node.children[-1].code = '{} * {}'.format(
                new_node.code, node.children[-1].children[-1].code)
            node.code = '{} * {}'.format(
                node.children[0].code, node.children[1].code)
        elif s_idx > 0:
            node.set_op('mul')
            node.add_child(Node(node.expr[:s_idx]))
            node.add_child(new_node)
            self.parse_stmt(node.children[0])
            node.code = '{} * {}'.format(
                node.children[0].code, node.children[1].code)
        elif pos < len(node.expr) - 1:
            node.set_op('mul')
            if new_node not in node.children:
                node.add_child(new_node)
            node.add_child(Node(node.expr[pos + 1:]))
            self.parse_stmt(node.children[-1])
            node.code = '{} * {}'.format(
                node.children[0].code, node.children[1].code)
        else:
            node.copy_node(new_node)

    def print_error_info(self):

        logs = log_buffer.getvalue()
        if logs != '':
            print(logs)
            # clear log buffer
            log_buffer.truncate(0)
            log_buffer.seek(0)
            return logs
        return ''

    def print_codes(self):

        if not self.data.llm_mode:
            logs = log_buffer.getvalue()
            if logs != '':
                print(logs)
                # clear log buffer
                log_buffer.truncate(0)
                log_buffer.seek(0)
                return logs
        code = r''''''
        vars = []
        self.data.get_tmp_arrays()
        for var in self.data.tmp_dict.keys():
            ty, dim = get_var_type(var, self.data.tmp_dict)
            if 'name' in self.data.tmp_dict[var].keys():
                var = self.data.tmp_dict[var]['name']
            if self.root.code.find(drop_square_brackets(var)) == -1:
                continue
            if var in vars:
                continue
            else:
                vars.append(var)
            if dim == [1]:
                def_code = ty + ' ' + var + ';'
            else:
                def_code = ty + ' ' + var
                while dim[-1] == 1:
                    dim = dim[:-1]
                for d in dim:
                    def_code += (f'[{d}]')
                def_code += ';'
            code += (def_code + '\n')
        if code != '':
            code += '\n'
        code_body = self.root.code
        if self.data.llm_mode:
            fail_pos = code_body.find('@@@failure@@@')
            if fail_pos != -1:
                code_body = code_body[:fail_pos]
        code += code_body

        print(code)
        return code
        # args = {}
        # for node in self.unknown_vars.values():
        #     fa = node.father
        #     for child in fa.children:
        #         if child.code == node.code:
        #             continue
        #         if child.op == 'var' and child.code in self.data.global_vars.keys():
        #             args[node.code] = type_dict[self.data.global_vars[child.code]['type']]

        #             break
        #     if node.code not in args.keys():
        #         args[node.code] = 'double'
        # func_name = ''
        # for verb in funcname_verb.keys():
        #     if verb in description:
        #         func_name += funcname_verb[verb]
        #         break
        # if func_name == '':
        #     func_name = "Calculate"
        # for noun in funcname_noun.keys():
        #     if noun in description:
        #         func_name += funcname_noun[noun]

        # #head = type_dict[out_put['type']] + ' ' + func_name + '('
        # head = 'void' + ' ' + func_name + '('
        # flag = False
        # for arg in args.keys():
        #     if flag:
        #         head += (', ' + args[arg] + ' ' + arg)
        #     else:
        #         flag = True
        #         head += (args[arg] + ' ' + arg)
        # head += ') {\n'
        # for sentence in code.split('\n'):
        #     head += ('    ' + sentence + '\n')
        # #head += ('    return ' + out_put['name'] + '\n')
        # head += '}'
        # print (head)


if __name__ == '__main__':
    # code = "Hwj= mlf(Hwj, 60.0);\r\nIF1 (|Hwj-Hwj0|>ValueHw)\r\ncnt_HwPick_j＝cnt_HwPick_j＋1;\r\nIF2 (cnt_HwPick_j <6)\r\nHwj＝Hwj0;\r\nELSE2\r\nHwj0＝Hwj;\r\ncnt_HwPick_j＝0;\r\nENDIF2\r\nELSE1\r\nHwj0＝Hwj;\r\ncnt_HwPick_j＝0;\r\nENDIF1\r\n"
    code = 'a = 1 / 2 * 3;'
    parser = Parser(code, '../configs/dicts/config_tmp.json')
    parser.parse()
    parser.print_codes()
